--- id: TASK-021 title: PDF / printable export in the house style status: "\U0001F7E2 In progress" assignee: [] created_date: '2026-06-29 20:49' updated_date: '2026-06-30 00:21' labels: - feature - release-1 dependencies: [] priority: medium ordinal: 21000 --- ## Description Add a glint command/keybind to export the current document as a clean, printable PDF (or print-ready HTML) in the AppKit house style — matching what _shared-app-kit/markdown-doc-kit already produces for the browser. Reuse that kit as the source of truth rather than reinventing styling: it has doc.css (tokens, the seven themes — flexoki/-dark, uchu/-dark, humdrum/-dark, eink — document typography, and the @media print rules), embedded fonts (Awke, Untitled Sans, Name Mono), and pagination conventions (opening '# Title' becomes a centered cover page; every '## Section' starts a new page; '{.page-break}' forces a break; US Letter, 1in margins; print collapses to black-on-white). Approach options to decide during design: - Generate a self-contained HTML (doc.css + fonts + rendered markdown baked in, like the kit's 'Save HTML') and either (a) open it in the browser so the user hits Print → Save as PDF, or (b) shell out to a headless converter (Chromium --headless --print-to-pdf, wkhtmltopdf, or weasyprint/pandoc+Prince) to write a .pdf directly. - Keep glint dependency-light: prefer 'emit HTML + open in browser' as the zero-extra-binary path; treat direct-to-PDF (needs an external tool) as optional/detected. - Map glint's active theme to the kit theme where they line up (flexoki light/dark already shared). Out of scope: reimplementing the kit's interactive features (checkbox toggle, drag reorder) in glint. ## Acceptance Criteria - [ ] #1 A glint command/keybind exports the current buffer to a printable artifact (PDF or print-ready self-contained HTML) in the markdown-doc-kit house style - [ ] #2 Output reuses the kit's doc.css + embedded fonts and its print conventions (cover page from '# Title', page-per '## Section', US Letter, black-on-white print) - [ ] #3 The chosen path is documented (browser print-to-PDF vs headless converter) and degrades gracefully when an optional external converter is absent - [ ] #4 README/help document the export command - [ ] #5 Fonts are user-configurable (config keys for display/body/mono), not hard-wired to the kit's bundled Awke/Untitled Sans/Name Mono — glint is distributed to other people who don't have those licensed fonts - [ ] #6 Export is portable off this machine: ships sane open/system-font fallbacks by default and works with no personal assets present; any bundled font must be redistributable, otherwise reference by name with fallbacks - [ ] #7 The needed kit assets (doc.css + print rules, HTML skeleton, any redistributable fonts) are vendored INTO this repo and embedded in the binary via go:embed — nothing is read from the external _shared-app-kit path at runtime, so a 'brew install glint' on another machine has everything it needs ## Implementation Notes Portability constraint (user): glint is installed by people who are NOT on this machine and do NOT have the kit's bundled fonts (Awke, Untitled Sans, Name Mono — personal/licensed). So the export must NOT hard-embed those. Fonts must be user-configurable (display/body/mono config keys, reusing the doc.css --font-* tokens) with safe open/system fallbacks (e.g. Georgia / system-ui / ui-monospace) so output looks fine with zero personal assets. Only redistributable fonts may be embedded by default. Packaging: glint must be self-contained. Copy/build the required kit pieces (doc.css + the @media print rules, the render HTML skeleton, only redistributable fonts) into the glint repo (e.g. internal/export/assets/) and embed them with go:embed so they ship inside the binary. Do NOT depend on /Users/kortum/Developer/Home/_shared-app-kit/markdown-doc-kit at runtime — that path doesn't exist on users' machines. Decide a vendor/sync story (a script that re-copies from the kit on update, or a one-time fork) so the embedded copy can be refreshed when the kit's house style changes; strip the licensed Awke/Untitled Sans/Name Mono @font-face blocks during that copy, leaving the --font-* tokens + fallbacks (ties to the configurable-fonts AC).